package com.yupi.oj.service.impl;

import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.yupi.oj.common.ErrorCode;
import com.yupi.oj.exception.BusinessException;
import com.yupi.oj.mapper.QuestionMapper;
import com.yupi.oj.model.dto.question.ExampleDTO;
import com.yupi.oj.model.dto.question.QuestionAddRequest;
import com.yupi.oj.model.dto.question.QuestionEditRequest;
import com.yupi.oj.model.dto.question.QuestionPageRequest;
import com.yupi.oj.model.entity.Question;
import com.yupi.oj.model.entity.User;
import com.yupi.oj.model.vo.QuestionVO;
import com.yupi.oj.service.QuestionService;
import com.yupi.oj.service.UserService;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @author yanghaifeng
 * @description 针对表【question(题目表)】的数据库操作Service实现
 * @createDate 2024-04-11 15:36:41
 */
@Service
public class QuestionServiceImpl extends ServiceImpl<QuestionMapper, Question>
        implements QuestionService {

    @Resource
    private StringRedisTemplate stringRedisTemplate;

    /**
     * 题目编号 Redis Key
     */
    private static final String QUESTION_NO_KEY = "question_no";

    @Autowired
    private UserService userService;

    @Transactional(rollbackFor = Exception.class)
    @Override
    public Long add(QuestionAddRequest questionAddRequest, HttpServletRequest request) {
        String title = questionAddRequest.getTitle();
        String description = questionAddRequest.getDescription();
        String input = questionAddRequest.getInput();
        String output = questionAddRequest.getOutput();
        List<ExampleDTO> exampleDTOList = questionAddRequest.getExampleDTOList();
        String tip = questionAddRequest.getTip();
        String difficultLevel = questionAddRequest.getDifficultLevel();
        List<String> tagList = questionAddRequest.getTagList();
        Integer memoryLimit = questionAddRequest.getMemoryLimit();
        Integer timeLimit = questionAddRequest.getTimeLimit();

        // 请参校验
        if (StrUtil.hasBlank(title, description, input, output, tip, difficultLevel)) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR);
        }
        if (ObjectUtil.hasNull(memoryLimit, timeLimit)) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR);
        }
        if (ObjectUtil.hasEmpty(exampleDTOList, tagList)) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR);
        }

        // 逻辑校验
        // 项目标题不能重复
        Question questionByTitle = this.getOne(Wrappers.lambdaQuery(Question.class)
                .eq(Question::getTitle, title));
        if (ObjectUtil.isNotNull(questionByTitle)) {
            throw new BusinessException(ErrorCode.OPERATION_ERROR, "改题目标题不能重复");
        }

        // 获取题目编号
        Question question = QuestionAddRequest.pojoToBean(questionAddRequest);
        Long questionNo = stringRedisTemplate.opsForValue().increment(QUESTION_NO_KEY);
        User loginUser = userService.getLoginUser(request);
        question.setCreateBy(loginUser.getUserAccount());
        question.setUpdateBy(loginUser.getUserAccount());
        question.setNo(questionNo);

        // 数据持久化
        this.save(question);
        return question.getId();
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public Boolean delete(Long id, HttpServletRequest request) {
        // 请参校验
        if (ObjectUtil.isNull(id)) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR);
        }
        // 逻辑校验
        Question question = this.getById(id);
        if (ObjectUtil.isNull(question)) {
            throw new BusinessException(ErrorCode.NOT_FOUND_ERROR);
        }
        return this.removeById(id);
    }

    @Override
    public Boolean edit(QuestionEditRequest questionEditRequest, HttpServletRequest request) {
        Long id = questionEditRequest.getId();
        String title = questionEditRequest.getTitle();
        String description = questionEditRequest.getDescription();
        String input = questionEditRequest.getInput();
        String output = questionEditRequest.getOutput();
        List<ExampleDTO> exampleDTOList = questionEditRequest.getExampleDTOList();
        String tip = questionEditRequest.getTip();
        String difficultLevel = questionEditRequest.getDifficultLevel();
        List<String> tagList = questionEditRequest.getTagList();
        Integer memoryLimit = questionEditRequest.getMemoryLimit();
        Integer timeLimit = questionEditRequest.getTimeLimit();

        // 请参校验
        if (StrUtil.hasBlank(title, description, input, output, tip, difficultLevel)) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR);
        }
        if (ObjectUtil.hasNull(id, memoryLimit, timeLimit)) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR);
        }
        if (ObjectUtil.hasEmpty(exampleDTOList, tagList)) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR);
        }


        // 逻辑校验
        // 问题是否存在
        Question question = this.getById(id);
        if (ObjectUtil.isNull(question)) {
            throw new BusinessException(ErrorCode.NOT_FOUND_ERROR, "问题不存在");
        }

        // 数据持久化
        QuestionEditRequest.pojoToBean(questionEditRequest, question);
        User loginUser = userService.getLoginUser(request);
        question.setUpdateBy(loginUser.getUserAccount());
        return this.updateById(question);
    }

    @Override
    public QuestionVO queryById(Long id) {
        // 请参校验
        if (ObjectUtil.isNull(id)) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR);
        }
        Question question = this.getById(id);
        if (ObjectUtil.isNull(question)) {
            throw new BusinessException(ErrorCode.NOT_FOUND_ERROR, "问题不存在");
        }
        return QuestionVO.beanToVO(question);
    }

    @Override
    public Page<QuestionVO> queryPage(Page<Question> page, QuestionPageRequest questionPageRequest) {
        Page<QuestionVO> result = new Page<>();
        // 分页查询
        page = baseMapper.queryPage(page, questionPageRequest);

        // 数据转换
        BeanUtils.copyProperties(page, result, "records");
        List<Question> records = page.getRecords();
        if (ObjectUtil.isNotEmpty(records)) {
            List<QuestionVO> collect = records.stream().map(QuestionVO::beanToVO).collect(Collectors.toList());
            result.setRecords(collect);
        }
        return result;
    }

    @Override
    public List<QuestionVO> queryList(QuestionPageRequest questionPageRequest) {
        String title = questionPageRequest.getTitle();
        String difficultLevel = questionPageRequest.getDifficultLevel();
        List<String> tagList = questionPageRequest.getTagList();

        List<QuestionVO> result = new ArrayList<>();
        // 分页查询
        LambdaQueryWrapper<Question> queryWrapper = Wrappers.lambdaQuery(Question.class);
        queryWrapper.like(StrUtil.isNotBlank(title), Question::getTitle, title);
        queryWrapper.eq(StrUtil.isNotBlank(difficultLevel), Question::getDifficultLevel, difficultLevel);
        if (ObjectUtil.isNotEmpty(tagList)) {
            for (String tag : tagList) {
                queryWrapper.eq(StrUtil.isNotBlank(tag), Question::getTag, tag);
            }
        }
        List<Question> list = this.list(queryWrapper);

        // 数据转换
        if (ObjectUtil.isNotEmpty(list)) {
            result = list.stream().map(QuestionVO::beanToVO).collect(Collectors.toList());
        }
        return result;
    }
}




